#ifndef ESTRATEGIAALMACENAMIENTOBSHARP_H_
#define ESTRATEGIAALMACENAMIENTOBSHARP_H_

#include "BloqueBSharp.h"
#include "DatoBSharp.h"
#include "AdministradorBufferingBSharp.h"

namespace Toolkit
{

class HandlerActualizacionPadre;

class ControladorAlmacenamientoBSharp
{
public:
	ControladorAlmacenamientoBSharp(
			AdministradorBufferingBSharp &administradorBuffering,
			const TipoSerializacion &tSerializacion,
			const unsigned long int &tamanoBloque, Almacenamiento &primario,
			WrapperComponente &wrapperPrimario, Almacenamiento &secundario,
			WrapperComponente &wrapperSecundario);

	//Pata reconstruirlo
	ControladorAlmacenamientoBSharp(
			AdministradorBufferingBSharp &administradorBuffering,
			const TipoSerializacion &tSerializacion,
			const unsigned long int &tamanoBloque,
			const unsigned long int &alturaBSharp);

	virtual ~ControladorAlmacenamientoBSharp();

	virtual void guardarDato(Almacenamiento &almacenamiento, const Dato &dato,
			const Clave &clave, const unsigned long int posicion,
			WrapperComponente &wrapper);

	virtual void eliminarDato(Almacenamiento &almacenamiento,
			const long unsigned int posicion, Dato &dato, const Clave &clave,
			WrapperComponente &wrapper);

	virtual void recuperarComponente(Almacenamiento &almacenamiento,
			const unsigned long int &posicion, WrapperComponente &wrapper);

	virtual void guardarComponente(Almacenamiento &almacenamiento,
			const unsigned long int &posicion, WrapperComponente &wrapper);

	virtual unsigned long int guardarComponente(Almacenamiento &almacenamiento,
			WrapperComponente &wrapper);

	void imprimirArbol(Almacenamiento &almacenamiento,
			const unsigned long int posicion) const;

	unsigned long int getAlturaBSharp() const;

	void setDatoAuxiliar (const DatoBSharp &dato);


private:

	friend class HandlerActualizacionPadre;

	virtual bool esRaiz(const BloqueBSharp &bloque) const;

	unsigned long int buscarPadre(const BloqueBSharp *bloque) const;

	void agregarDato(Almacenamiento &almacenamiento, BloqueBSharp &bloque,
			const Dato &dato, const Clave &clave,
			const unsigned long int &posicion, WrapperComponente &wrapper);

	void manejarUnderflow(Almacenamiento &almacenamiento, BloqueBSharp &bloque,
			const unsigned long int posicion, WrapperComponente &wrapper,
			const long int &posPadre, BloqueBSharp *padre,
			const long int &posIzq, BloqueBSharp *siblingIzq,
			const long int &posDer, BloqueBSharp *siblingDer);

	void manejarOverflow(Almacenamiento &almacenamiento, BloqueBSharp &bloque,
			const unsigned long int posicion, WrapperComponente &wrapper,
			BloqueBSharp *siblingIzq, const long int & posIzq,
			BloqueBSharp *siblingDer, const long int &posDer);

	void manejarOverflowRaiz(Almacenamiento &almacenamiento,
			BloqueBSharp &bloque, const unsigned long int posicion,
			WrapperComponente &wrapper);

	void balanceoEntreDosIzq(Almacenamiento &almacenamiento,
			BloqueBSharp &bloque, const unsigned long int posicion,
			WrapperComponente &wrapper, BloqueBSharp &siblingIzq,
			unsigned long int posIzqEnPrimario);

	void balanceoEntreDosDer(Almacenamiento &almacenamiento,
			BloqueBSharp &bloque, const unsigned long int posicion,
			WrapperComponente &wrapper, BloqueBSharp &siblingDer,
			unsigned long int posDerEnPrimario);

	void guardarBloqueEnPosicion(BloqueBSharp &bloque,
			Almacenamiento &almacenamiento, const unsigned long int &posicion,
			WrapperComponente &wrapper);

	unsigned long int guardarBloqueNuevo(BloqueBSharp &bloque,
			Almacenamiento &almacenamiento, WrapperComponente &wrapper);

	AdministradorBufferingBSharp &administradorBuffering;
	unsigned long int alturaBsharp;

	TipoSerializacion tSerializacion;

	HandlerActualizacionPadre *handlerPadre;

	unsigned long int tamanoBloque;
	Dato *datoAuxiliar;

};

}

#endif /* ESTRATEGIAALMACENAMIENTOBSHARP_H_ */
